﻿using System;
using System.IO;
using Application = System.Windows.Application;
using StreamResourceInfo = System.Windows.Resources.StreamResourceInfo;

namespace Duellum.Core.Resources
{
	public static class DuelResources
	{
		static public string MakeAbsolutePath(string relativePath)
		{
			return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, relativePath);
		}
		
		/// <summary>
		/// Inspired by this: http://msdn.microsoft.com/en-us/library/aa970494.aspx
		/// </summary>
		static private StreamResourceInfo GetResourceFromUri(Uri uri)
		{
			if (!uri.IsAbsoluteUri) {
				try {
					return GetResourceOrContent(uri);
				} catch (IOException) {
					//try load a file using a relative path (WPF doesn't do this for security reasons)
					//string path = Path.Combine(Environment.CurrentDirectory, uri.ToString());
					string path = MakeAbsolutePath(uri.ToString().TrimStart('/'));
					return GetFileResource(path);
				}
			} else {
				if (uri.Scheme == "pack") {
					if (uri.Authority == "siteoforigin:,,,") {
						return Application.GetRemoteStream(uri);
					} else if (uri.Authority == "application:,,,") {
						return GetResourceOrContent(uri);
					} else {
						throw new ApplicationException(string.Format("URI authority [{0}] not supportted", uri.Authority));
					}
				} else if (uri.IsFile) {
					return GetFileResource(uri);
				} else {
					throw new ApplicationException(string.Format("URI scheme [{0}] not supportted", uri.Scheme));
				}
			}
		}
		
		static public Stream GetStreamFromUri(Uri uri)
		{
			return GetResourceFromUri(uri).Stream;
		}

		static public bool TryGetResourceFromUri(Uri uri, out StreamResourceInfo res)
		{
			res = null;
			if (uri == null) return false;
			else {
				try {
					res = GetResourceFromUri(uri);
					return (res != null);
				} catch (IOException) {
					return false;
				} catch (ApplicationException) {
					return false;
				}
			}
		}

		private static StreamResourceInfo GetResourceOrContent(Uri uri)
		{
			return Application.GetResourceStream(uri)
				?? Application.GetContentStream(uri);
		}

		private static StreamResourceInfo GetFileResource(Uri uri)
		{
			return GetFileResource(uri.LocalPath);
		}

		private static StreamResourceInfo GetFileResource(string path)
		{
			//TODO: The FileStream can be left unreleased too easily. Should I read it to a MemoryStream?
			var stream = new FileStream(path, FileMode.Open, FileAccess.Read);
			return new StreamResourceInfo(stream, null);
		}
	}
}
